POV-Ray : Newsgroups : povray.programming : Improved intersection routine for CSG-Intersection objects : Re: Improved intersection routine for CSG-Intersection objects Server Time
6 Oct 2024 13:43:30 EDT (-0400)
  Re: Improved intersection routine for CSG-Intersection objects  
From: Wolfgang Wieser
Date: 18 Dec 2003 13:51:42
Message: <3fe1f73d@news.povray.org>
Thorsten Froehlich wrote:
>> For inline functions this is true. Not so for extern linkage.
> 
> You cannot have external linkage for template functions.
> 
You can. You just have to make sure that a specialisation for the 
used type is linked in extenally. 

>> The result is lots of inline code which results in larger executables
>> and eventually even in slower code.
> 
> Only if you use containers of many different types!  Modern linkers will
> eliminate multiple identical template function instances, thus you only
> see the code bloat in the object files, but not in the final linked
> program.
> 
Correct. But all as you normally need to have all template stuff 
inline, this results in a lot of inline code duplication. 

>>>> But _not_ for real simple types. For "I quickly need a vector", using
>>>> double v[3] is still faster than anything using operator new or
>>>> applying a fancy con/destructor.
>>>
>>> Sorry, but if you need a local variable, who said you should use new???
>>>
>> So, if you need a local variable of just such a type we're talking about,
>> i.e. a class which simply contains a pointer to an internal class,
>> then the class will be allocated on the stack (okay, fast) and the
>> internal class will be allocated using operator new on the heap.
> 
> But only if there is data.  If properly designed, if there is no data, no
> memory should be allocated.  Unless you use fixed-size data in C, you will
> have exactly the same amount of work.  And there is nothing that keeps you
> from using fixed-size data in C++, except that it is bad style, in both
> languages.
> 
I have the feeling that we're not getting the point of what we want 
to tell each other... 

>> All that happens when you call the constructor and initialize your
>> class. For the normal use, this is just what you want because when
>> you pass the class to a function, it is quite fast (just increase
>> reference counter). But if the object is simply a local var you want
>> on the stack, then the overhead is considerably.
> 
> Why would you reference count the internal data of most classes?  You seem
> to be thinking about some special case, but even then, how would a
> reference counting C++ implementation be slower than a similar C
> implementation?
> 
Because the C construction does no reference counting. You allocate 
a pointer once and then use it. And the designer knows where it was 
allocated, "who" is responsible for the pointer and its lifetime. 

Yes, that's insecure like hell but faster and smaller. 
And for good designs, it even :) works...

> Well, you should really not be doing reference counting inside a class in
> the first place.  If you share data among several objects of the same
> class,
> most of the time you have a serious design problem.  And again, the
> reference counting would not work differently in C, so there is again no
> difference in overhead!
> 
I need to make an example. 

A fairly normal implementation of the class which just holds a 
pointer to an internal class. As the internal class may be shared 
among several instances, we use reference counting. 

class MyObject
{
        _MyInternalObject *o;
        MyObject(const MyObject &m) : o(m.o)
        {  if(o) o->add_reference();  }
        MyObject(params_for_obj)
        {  o=new _MyInternalObject(params_for_obj);  o->add_reference();  }
        ~MyObject()
        {  if(o) o->sub_reference();  }
};

This is fairly straight forward and how things like std::string, etc, 
work. 

Overhead at function call (call by value): just copying the pointer 
and adding a reference (i.e. ++ref_cnt;)
[Much better than call-by-value of the complete internal class but 
worse than simply passing a pointer/reference]

So, now say you need a temporary of that class: 

foo()
{
        MyObject obj(pbject_params);
        obj.do_sth();  return(obj.sth_else());
}

That will (1) allocate some bytes on the stack (fast) and then 
(2) allocate internal object using operator new (slow). 

That is what I had in mind. 

I still am the opinion that it is pretty hard if not (nearly?) impossible 
to design really fast C++ code (i.e. as fast as insecure C code) when one 
forces itself to stick to all the "good style" guidelines. (Depends on 
what one defines as "good style"). 

So, of course gained savety comes at some price. It's just to get it 
as cheap as possible. 

Wolfgang


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.